<?php

declare(strict_types=1);

namespace NanQi\Hope\Traits;

use Hyperf\Utils\Codec\Json;
use Hyperf\Utils\Context;
use Hyperf\Utils\Contracts\Arrayable;
use Hyperf\Utils\Contracts\Jsonable;
use NanQi\Hope\Constants\StatusCodeConstants;
use NanQi\Hope\Exception\BusinessException;
use NanQi\Hope\Hope;
use NanQi\Hope\Listener\QueryExecListener;

trait ResponseFormatTrait {

    /**
     * @param null|array|Arrayable|Jsonable|string $response
     * @return string
     */
    protected function successFormat($response)
    {
        $ret = [];
        $ret['code'] = 200;
        $ret['msg'] = '';
        $ret['data'] = $response ?? new \stdClass();

        $isProduct = Hope::isProduct();

        if (!$isProduct) {
            $sqlKey = class_basename(QueryExecListener::class);

            if (Context::has($sqlKey)) {
                $eventSqlList = Context::get($sqlKey);
                $ret['_sql'] = $eventSqlList;
            }
        }

        return Json::encode($ret);
    }

    protected function errorFormat(int $statusCode,
                                string $errorMessage,
                                $data = null,
                                int $errorCode = 0) {
        if ($errorCode === 0) {
            $errorCode = $statusCode;
        }

        $ret = [
            'code'    => $errorCode,
            'msg'     => $errorMessage,
            'data'    => []
        ];

        $isProduct = Hope::isProduct();
        if (!$isProduct && $data) {
            $ret['data'] = $data;
        }

        return Json::encode($ret);
    }

    /**
     * 返回错误
     * @param int $errorCode
     * @param string $errorMessage
     */
    protected function retError(int $errorCode, string $errorMessage = null)
    {
        abort($errorCode, $errorMessage);
    }

    protected function errorStatusCode(int $statusCode, string $message = null)
    {
        if (!$message) {
            $message = StatusCodeConstants::getMessage($statusCode);
        }

        throw new BusinessException($statusCode,
            $message,
            $statusCode);
    }

    /**
     * Return a 404 not found error.
     * @param string|null $message
     * @return void
     */
    protected function errorNotFound(string $message = null)
    {
        $this->errorStatusCode(StatusCodeConstants::S_404_NOT_FOUND, $message);
    }

    /**
     * Return a 403 forbidden error.
     * @param string|null $message
     * @return void
     */
    protected function errorForbidden(string $message = null)
    {
        $this->errorStatusCode(StatusCodeConstants::S_403_FORBIDDEN, $message);
    }

    /**
     * Return a 401 unauthorized error.
     * @param string $message
     * @return void
     */
    protected function errorUnauthorized(string $message = null)
    {
        $this->errorStatusCode(StatusCodeConstants::S_401_UNAUTHORIZED, $message);
    }

    /**
     * 操作数据库异常
     * @param string|null $message
     */
    protected function errorOperationDataBase(string $message = null)
    {
        $this->errorStatusCode(StatusCodeConstants::S_406_OPERATION_DATABASE, $message);
    }

    /**
     * 系统繁忙
     * @param string|null $message
     */
    protected function errorBusy(string $message = null)
    {
        $this->errorStatusCode(StatusCodeConstants::S_407_BUSY, $message);
    }

    /**
     * 数据错误
     * @param string|null $message
     */
    protected function errorDataError(string $message = null)
    {
        $this->errorStatusCode(StatusCodeConstants::S_408_DATA_ERROR, $message);
    }
}